using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO.Ports;
using System.Windows.Forms;
using HslCommunication;
using HslCommunication.Core;
using HslCommunication.ModBus;
using HslCommunication.Profinet.Siemens;
using Opc.Ua;
using OpcUaHelper;
using WIT.DAQ.Core.Enums;
using WIT.DAQ.Core.Models;
using WIT.DAQ.Core.Protocols.Socket;

namespace WIT.DAQ.Core.Forms;

/// <summary>
/// 监控界面-写入值
/// </summary>
internal class WriteValueForm : BaseForm
{
	/// <summary>
	/// 设备
	/// </summary>
	private Device DEVICE;

	/// <summary>
	/// 采集项
	/// </summary>
	private DAQItem DAQITEM;

	/// <summary>
	/// 协议连接实例
	/// </summary>
	private object CONNECTION;

	/// <summary>
	/// Required designer variable.
	/// </summary>
	private IContainer components = null;

	private Button btnCancel;

	private Button btnWrite;

	private TextBox txtDevice;

	private Label label1;

	private Label label2;

	private TextBox txtValue;

	private Label label3;

	private TextBox txtProtocol;

	private Label lblAddress;

	private TextBox txtAddress;

	private Label label5;

	private TextBox txtDataType;

	/// <summary>
	///
	/// </summary>
	/// <param name="device">设备</param>
	/// <param name="daqItem">采集项</param>
	/// <param name="defaultValue">默认值</param>
	/// <param name="connectionIns">连接实例</param>
	internal WriteValueForm(Device device, DAQItem daqItem, string defaultValue = "", object connectionIns = null)
	{
		InitializeComponent();
		DEVICE = device;
		DAQITEM = daqItem;
		CONNECTION = connectionIns;
		txtValue.Text = defaultValue;
	}

	private void WriteValueForm_Load(object sender, EventArgs e)
	{
		txtDevice.Text = DEVICE.Name;
		txtProtocol.Text = DEVICE.Protocol.ToString();
		txtAddress.Text = ((DEVICE.Protocol == EnumProtocol.OPCUA) ? DAQITEM.NodeId : DAQITEM.Address);
		txtDataType.Text = DAQITEM.DataType;
		ToolTip toolTip = new ToolTip();
		toolTip.AutoPopDelay = 3000;
		toolTip.InitialDelay = 500;
		toolTip.ReshowDelay = 500;
		toolTip.ShowAlways = true;
		toolTip.SetToolTip(txtAddress, (DEVICE.Protocol == EnumProtocol.OPCUA) ? DAQITEM.NodeId : DAQITEM.Address);
		ToolTip toolTip2 = new ToolTip();
		toolTip2.AutoPopDelay = 3000;
		toolTip2.InitialDelay = 500;
		toolTip2.ReshowDelay = 500;
		toolTip2.ShowAlways = true;
		toolTip2.SetToolTip(lblAddress, (DEVICE.Protocol == EnumProtocol.OPCUA) ? DAQITEM.NodeId : DAQITEM.Address);
		txtValue.Select();
	}

	/// <summary>
	/// 写入值
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param> 
	private async void btnWrite_Click(object sender, EventArgs e)
	{
		btnWrite.Enabled = false;
		bool flag = false;
		string errMsg = string.Empty;
		object connectionIns = null;
		try
		{
			switch (DEVICE.Protocol)
			{
			case EnumProtocol.OPCUA:
				if (CONNECTION != null && CONNECTION.GetType() == typeof(OpcUaClient))
				{
					connectionIns = CONNECTION;
				}
				else
				{
					connectionIns = new OpcUaClient();
					if (DEVICE.NeedAccount.HasValue && DEVICE.NeedAccount.Value)
					{
						((OpcUaClient)connectionIns).UserIdentity = new UserIdentity(DEVICE.Account, DEVICE.Pwd);
					}
					await ((OpcUaClient)connectionIns).ConnectServer(DEVICE.Url);
				}
				flag = Common.WriteValues(connectionIns, DEVICE, new List<DAQItem> { DAQITEM }, new List<object> { txtValue.Text.Trim() }, out errMsg);
				break;
			case EnumProtocol.S7:
				if (CONNECTION != null && CONNECTION.GetType() == typeof(SiemensS7Net))
				{
					connectionIns = CONNECTION;
				}
				else
				{
					connectionIns = new SiemensS7Net((SiemensPLCS)DEVICE.Model)
					{
						IpAddress = DEVICE.IP,
						Port = DEVICE.Port,
						Rack = Convert.ToByte(DEVICE.Rack),
						Slot = Convert.ToByte(DEVICE.Slot)
					};
					OperateResult result = ((SiemensS7Net)connectionIns).ConnectServer();
					if (!result.IsSuccess)
					{
						MessageBox.Show($"{DEVICE.Protocol}尝试连接设备[{DEVICE.Name}]时失败！\r错误代码：{result.ErrorCode}\r错误信息：{result.Message}");
						return;
					}
				}
				flag = Common.WriteValues(connectionIns, DEVICE, new List<DAQItem> { DAQITEM }, new List<object> { txtValue.Text.Trim() }, out errMsg);
				break;
			case EnumProtocol.ModbusTcp:
				if (CONNECTION != null && CONNECTION.GetType() == typeof(ModbusTcpNet))
				{
					connectionIns = CONNECTION;
				}
				else
				{
					connectionIns = new ModbusTcpNet(DEVICE.IP, DEVICE.Port, Convert.ToByte(DEVICE.Station))
					{
						AddressStartWithZero = DEVICE.AddressStartWithZero.Value,
						DataFormat = (DataFormat)Enum.Parse(typeof(DataFormat), DEVICE.DataFormat, ignoreCase: true),
						IsStringReverse = DEVICE.IsStringReverse.Value
					};
					OperateResult result2 = ((ModbusTcpNet)connectionIns).ConnectServer();
					if (!result2.IsSuccess)
					{
						MessageBox.Show($"{DEVICE.Protocol}尝试连接设备[{DEVICE.Name}]时失败！\r错误代码：{result2.ErrorCode}\r错误信息：{result2.Message}");
						return;
					}
				}
				flag = Common.WriteValues(connectionIns, DEVICE, new List<DAQItem> { DAQITEM }, new List<object> { txtValue.Text.Trim() }, out errMsg);
				break;
			case EnumProtocol.ModbusRtu:
				if (CONNECTION != null && CONNECTION.GetType() == typeof(ModbusRtu))
				{
					connectionIns = CONNECTION;
				}
				else
				{
					connectionIns = new ModbusRtu(Convert.ToByte(DEVICE.Station))
					{
						AddressStartWithZero = DEVICE.AddressStartWithZero.Value,
						DataFormat = (DataFormat)Enum.Parse(typeof(DataFormat), DEVICE.DataFormat, ignoreCase: true),
						IsStringReverse = DEVICE.IsStringReverse.Value
					};
					((ModbusRtu)connectionIns).SerialPortInni(DEVICE.ComPort, Convert.ToInt32(DEVICE.BaudRate), Convert.ToInt32(DEVICE.DataBits), (StopBits)DEVICE.StopBits.Value, (Parity)DEVICE.Parity.Value);
					((ModbusRtu)connectionIns).Open();
				}
				flag = Common.WriteValues(connectionIns, DEVICE, new List<DAQItem> { DAQITEM }, new List<object> { txtValue.Text.Trim() }, out errMsg);
				break;
			default:
				throw new Exception($"未知的通信协议[{DEVICE.Protocol}]");
			case EnumProtocol.Socket:
				break;
			}
			if (flag)
			{
				Close();
			}
			else
			{
				MessageBox.Show("尝试写入值时失败！\r" + errMsg);
			}
		}
		catch (Exception ex2)
		{
			Exception ex = ex2;
			if (ex.Message.Contains("未知的通信协议"))
			{
				throw ex;
			}
			MessageBox.Show(ex.Message);
		}
		finally
		{
			btnWrite.Enabled = true;
			if (CONNECTION == null)
			{
				switch (DEVICE.Protocol)
				{
				case EnumProtocol.OPCUA:
					(connectionIns as OpcUaClient).Disconnect();
					break;
				case EnumProtocol.S7:
					(connectionIns as SiemensS7Net).ConnectClose();
					break;
				case EnumProtocol.ModbusTcp:
					(connectionIns as ModbusTcpNet).ConnectClose();
					break;
				case EnumProtocol.ModbusRtu:
					(connectionIns as ModbusRtu).Close();
					break;
				case EnumProtocol.Socket:
					(connectionIns as TCPClient).DisConnect();
					break;
				default:
					throw new Exception($"未知的通信协议[{DEVICE.Protocol}]");
				}
			}
		}
		if (flag)
		{
			Close();
		}
		else
		{
			MessageBox.Show("尝试写入值时失败！\r" + errMsg);
		}
	}

	/// <summary>
	/// 回车键触发写入
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	private void txtValue_KeyDown(object sender, KeyEventArgs e)
	{
		if (e.KeyCode == Keys.Return)
		{
			btnWrite_Click(null, null);
		}
	}

	/// <summary>
	/// 关闭
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	private void btnCancel_Click(object sender, EventArgs e)
	{
		Close();
	}

	/// <summary>
	/// ESC关闭
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	private void WriteValueForm_KeyDown(object sender, KeyEventArgs e)
	{
		if (e.KeyCode == Keys.Escape)
		{
			btnCancel_Click(null, null);
		}
	}

	/// <summary>
	/// Clean up any resources being used.
	/// </summary>
	/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
	protected override void Dispose(bool disposing)
	{
		if (disposing && components != null)
		{
			components.Dispose();
		}
		base.Dispose(disposing);
	}

	/// <summary>
	/// Required method for Designer support - do not modify
	/// the contents of this method with the code editor.
	/// </summary>
	private void InitializeComponent()
	{
		this.btnCancel = new System.Windows.Forms.Button();
		this.btnWrite = new System.Windows.Forms.Button();
		this.txtDevice = new System.Windows.Forms.TextBox();
		this.label1 = new System.Windows.Forms.Label();
		this.label2 = new System.Windows.Forms.Label();
		this.txtValue = new System.Windows.Forms.TextBox();
		this.label3 = new System.Windows.Forms.Label();
		this.txtProtocol = new System.Windows.Forms.TextBox();
		this.lblAddress = new System.Windows.Forms.Label();
		this.txtAddress = new System.Windows.Forms.TextBox();
		this.label5 = new System.Windows.Forms.Label();
		this.txtDataType = new System.Windows.Forms.TextBox();
		base.SuspendLayout();
		this.btnCancel.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right;
		this.btnCancel.Location = new System.Drawing.Point(287, 185);
		this.btnCancel.Name = "btnCancel";
		this.btnCancel.Size = new System.Drawing.Size(75, 23);
		this.btnCancel.TabIndex = 6;
		this.btnCancel.Text = "取消(&C)";
		this.btnCancel.UseVisualStyleBackColor = true;
		this.btnCancel.Click += new System.EventHandler(btnCancel_Click);
		this.btnWrite.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right;
		this.btnWrite.Location = new System.Drawing.Point(206, 185);
		this.btnWrite.Name = "btnWrite";
		this.btnWrite.Size = new System.Drawing.Size(75, 23);
		this.btnWrite.TabIndex = 5;
		this.btnWrite.Text = "写入(&W)";
		this.btnWrite.UseVisualStyleBackColor = true;
		this.btnWrite.Click += new System.EventHandler(btnWrite_Click);
		this.txtDevice.Enabled = false;
		this.txtDevice.Location = new System.Drawing.Point(131, 30);
		this.txtDevice.MaxLength = 0;
		this.txtDevice.Name = "txtDevice";
		this.txtDevice.Size = new System.Drawing.Size(150, 21);
		this.txtDevice.TabIndex = 0;
		this.label1.AutoSize = true;
		this.label1.Location = new System.Drawing.Point(84, 33);
		this.label1.Name = "label1";
		this.label1.Size = new System.Drawing.Size(41, 12);
		this.label1.TabIndex = 2;
		this.label1.Text = "设备：";
		this.label2.AutoSize = true;
		this.label2.Location = new System.Drawing.Point(72, 142);
		this.label2.Name = "label2";
		this.label2.Size = new System.Drawing.Size(53, 12);
		this.label2.TabIndex = 2;
		this.label2.Text = "写入值：";
		this.txtValue.Location = new System.Drawing.Point(131, 139);
		this.txtValue.MaxLength = 0;
		this.txtValue.Name = "txtValue";
		this.txtValue.Size = new System.Drawing.Size(150, 21);
		this.txtValue.TabIndex = 4;
		this.txtValue.KeyDown += new System.Windows.Forms.KeyEventHandler(txtValue_KeyDown);
		this.label3.AutoSize = true;
		this.label3.Location = new System.Drawing.Point(84, 60);
		this.label3.Name = "label3";
		this.label3.Size = new System.Drawing.Size(41, 12);
		this.label3.TabIndex = 2;
		this.label3.Text = "协议：";
		this.txtProtocol.Enabled = false;
		this.txtProtocol.Location = new System.Drawing.Point(131, 57);
		this.txtProtocol.MaxLength = 0;
		this.txtProtocol.Name = "txtProtocol";
		this.txtProtocol.Size = new System.Drawing.Size(150, 21);
		this.txtProtocol.TabIndex = 1;
		this.lblAddress.AutoSize = true;
		this.lblAddress.Location = new System.Drawing.Point(42, 87);
		this.lblAddress.Name = "lblAddress";
		this.lblAddress.Size = new System.Drawing.Size(83, 12);
		this.lblAddress.TabIndex = 2;
		this.lblAddress.Text = "地址/NodeId：";
		this.txtAddress.Enabled = false;
		this.txtAddress.Location = new System.Drawing.Point(131, 84);
		this.txtAddress.MaxLength = 0;
		this.txtAddress.Name = "txtAddress";
		this.txtAddress.Size = new System.Drawing.Size(150, 21);
		this.txtAddress.TabIndex = 2;
		this.label5.AutoSize = true;
		this.label5.Location = new System.Drawing.Point(60, 114);
		this.label5.Name = "label5";
		this.label5.Size = new System.Drawing.Size(65, 12);
		this.label5.TabIndex = 2;
		this.label5.Text = "数据类型：";
		this.txtDataType.Enabled = false;
		this.txtDataType.Location = new System.Drawing.Point(131, 111);
		this.txtDataType.MaxLength = 0;
		this.txtDataType.Name = "txtDataType";
		this.txtDataType.Size = new System.Drawing.Size(150, 21);
		this.txtDataType.TabIndex = 3;
		base.AutoScaleDimensions = new System.Drawing.SizeF(6f, 12f);
		base.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
		base.ClientSize = new System.Drawing.Size(374, 220);
		base.Controls.Add(this.txtDataType);
		base.Controls.Add(this.label5);
		base.Controls.Add(this.txtValue);
		base.Controls.Add(this.label2);
		base.Controls.Add(this.txtAddress);
		base.Controls.Add(this.lblAddress);
		base.Controls.Add(this.txtProtocol);
		base.Controls.Add(this.label3);
		base.Controls.Add(this.txtDevice);
		base.Controls.Add(this.label1);
		base.Controls.Add(this.btnWrite);
		base.Controls.Add(this.btnCancel);
		base.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
		base.MaximizeBox = false;
		base.MinimizeBox = false;
		base.Name = "WriteValueForm";
		base.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
		this.Text = "手动写入值";
		base.Load += new System.EventHandler(WriteValueForm_Load);
		base.KeyDown += new System.Windows.Forms.KeyEventHandler(WriteValueForm_KeyDown);
		base.ResumeLayout(false);
		base.PerformLayout();
	}
}
